#pragma once
#include <iostream>
#include <string>
#include <memory>
#include <functional>
#include "DefinitionField.hpp"
#include "Communication.hpp"

namespace xu
{
    // 消息抽象类
    class BaseMessage
    {
    public:
        using Ptr = std::shared_ptr<BaseMessage>;
        virtual ~BaseMessage() = default;
        virtual xu::MType Mtype() { return _mtype; }                      // 返回消息类型
        virtual std::string Id() { return _id; }                          // 返回消息id
        virtual void SetMType(const xu::MType &mtype) { _mtype = mtype; } // 设置消息类型
        virtual void SetId(const std::string &id) { _id = id; }           // 设置消息id
        virtual std::string Serialization() = 0;                          // 序列化
        virtual bool Deserialization(const std::string &body) = 0;        // 反序列化
        virtual bool Check() = 0;                                         // 检测字段和类型
    private:
        xu::MType _mtype; // 消息类型
        std::string _id;  // 消息id
    };

    // 数据缓冲区抽象类
    class BaseBuffer
    {
    public:
        using Ptr = std::shared_ptr<BaseBuffer>;
        virtual ~BaseBuffer() = default;
        virtual int32_t PeekInt32() = 0;                      // 查看缓冲区前4字节
        virtual size_t ReadableBytes() = 0;                   // 可读字节大小
        virtual int32_t ReadIint32() = 0;                     // 读4字节并删除
        virtual void RetrieveInt32() = 0;                     // 删除4字节数据
        virtual std::string RetrieveAsString(size_t len) = 0; // 读取len字节
    };

    // 协议抽象类
    class BaseProtocol
    {
    public:
        using Ptr = std::shared_ptr<BaseProtocol>;
        virtual ~BaseProtocol() = default;
        virtual bool OnMessage(const BaseBuffer::Ptr &buf, BaseMessage::Ptr &msg) = 0; // 通过buf设置msg
        virtual bool CanProcessed(const BaseBuffer::Ptr &buf) = 0;                     // 能否取出
        virtual std::string Serialization(const BaseMessage::Ptr &msg) = 0;            // 序列化
    };

    // 连接抽象类
    class BaseConnection
    {
    public:
        using Ptr = std::shared_ptr<BaseConnection>;
        virtual ~BaseConnection() = default;
        virtual void Send(const BaseMessage::Ptr &msg) = 0; // 发送消息
        virtual void ShutDown() = 0;                        // 断开连接
        virtual bool Connected() = 0;                       // 是否在连接
    };

    using ConnectionCallback = std::function<void(const BaseConnection::Ptr &)>;                     // 连接成功时的回调函数
    using CloseCallback = std::function<void(const BaseConnection::Ptr &)>;                          // 连接关闭时的回调函数
    using MessageCallback = std::function<void(const BaseConnection::Ptr &, BaseMessage::Ptr &msg)>; // 缓冲区有数据时的回调函数

    // 抽象的服务端类
    class BaseServer
    {
    public:
        using Ptr = std::shared_ptr<BaseServer>;
        virtual ~BaseServer() = default;
        virtual void SetConnectionCallback(const ConnectionCallback &conncallback)
        {
            _conncallback = conncallback;
        }

        virtual void SetCloseCallback(const CloseCallback &closecallback)
        {
            _closecallback = closecallback;
        }

        virtual void SetMessageCallback(const MessageCallback &msgcallback)
        {
            _msgcallback = msgcallback;
        }

        virtual void Start() = 0;

    protected:
        ConnectionCallback _conncallback;
        CloseCallback _closecallback;
        MessageCallback _msgcallback;
    };

    class BaseClient
    {
    public:
        using Ptr = std::shared_ptr<BaseClient>;
        virtual ~BaseClient() = default;
        virtual void SetConnectionCallback(const ConnectionCallback &conncallback)
        {
            _conncallback = conncallback;
        }

        virtual void SetCloseCallback(const CloseCallback &closecallback)
        {
            _closecallback = closecallback;
        }

        virtual void SetMessageCallback(const MessageCallback &msgcallback)
        {
            _msgcallback = msgcallback;
        }

        virtual bool Send(const BaseMessage::Ptr &mes) = 0;
        virtual void ShutDown() = 0;
        virtual bool Connected() = 0;
        virtual void Connect() = 0;
        virtual BaseConnection::Ptr Connection() = 0;

    protected:
        ConnectionCallback _conncallback;
        CloseCallback _closecallback;
        MessageCallback _msgcallback;
    };

};